package models

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"

	"jlpay-sdk-go/pkg/jlpay/core"
	"jlpay-sdk-go/pkg/jlpay/utils"
)

// FileUploadRequest 文件上传请求基类
type FileUploadRequest struct {
	OrgBaseRequest
	FileType string `json:"file_type,omitempty"`
	FilePath string `json:"-"`
	file     io.Reader
}

// NewFileUploadRequest 创建文件上传请求
func NewFileUploadRequest() *FileUploadRequest {
	return &FileUploadRequest{}
}

// SetFileType 设置文件类型
func (r *FileUploadRequest) SetFileType(fileType string) *FileUploadRequest {
	r.FileType = fileType
	return r
}

// SetFilePath 设置文件路径
func (r *FileUploadRequest) SetFilePath(filePath string) *FileUploadRequest {
	r.FilePath = filePath
	return r
}

// GetFile 获取文件内容
func (r *FileUploadRequest) GetFile() io.Reader {
	return r.file
}

// GetAPIURI 获取API URI
func (r *FileUploadRequest) GetAPIURI() string {
	return "/open/file/upload"
}

// CheckRequiredParams 检查必需参数
func (r *FileUploadRequest) CheckRequiredParams(config *core.Config) error {
	if err := r.OrgBaseRequest.CheckRequiredParams(config); err != nil {
		return err
	}
	if r.FileType == "" {
		return fmt.Errorf("file_type不能为空")
	}
	if r.FilePath == "" {
		return fmt.Errorf("file_path不能为空")
	}

	// 打开文件
	file, err := os.Open(r.FilePath)
	if err != nil {
		return fmt.Errorf("打开文件失败: %w", err)
	}
	r.file = file
	return nil
}

// FileUploadResponse 文件上传响应
type FileUploadResponse struct {
	StandardResponse
	FileURL string `json:"file_url"`
	MediaID string `json:"media_id"`
}

// NewFileUploadResponse 创建文件上传响应
func NewFileUploadResponse() *FileUploadResponse {
	return &FileUploadResponse{}
}

// GetFileURL 获取文件URL
func (r *FileUploadResponse) GetFileURL() string {
	return r.FileURL
}

// GetMediaID 获取媒体文件ID
func (r *FileUploadResponse) GetMediaID() string {
	return r.MediaID
}

// MerchantFileUploadRequest 商管文件上传请求基类
type MerchantFileUploadRequest struct {
	OrgBaseRequest
	Meta     string `json:"meta,omitempty"`
	FilePath string `json:"-"`
	file     io.Reader
	fileName string
}

// SetMeta 设置媒体文件元信息
func (r *MerchantFileUploadRequest) SetMeta(filename string, fileContent []byte) *MerchantFileUploadRequest {
	// 计算文件SM3摘要
	digest, err := utils.GetDigestByType("SM3", fileContent)
	if err != nil {
		// 记录错误但不中断，避免在设置时出错
		utils.Debugf("计算文件摘要失败: %v", err)
		return r
	}

	abstract := base64.StdEncoding.EncodeToString(digest)

	metaInfo := map[string]interface{}{
		"filename": filename,
		"alg":      "SM3",
		"abstract": abstract,
	}

	metaBytes, err := json.Marshal(metaInfo)
	if err != nil {
		utils.Debugf("序列化meta信息失败: %v", err)
		return r
	}

	r.Meta = string(metaBytes)
	r.fileName = filename
	return r
}

// SetFile 设置文件内容
func (r *MerchantFileUploadRequest) SetFile(fileContent []byte) *MerchantFileUploadRequest {
	r.file = bytes.NewReader(fileContent)
	return r
}

// SetFileFromPath 从文件路径读取并设置文件内容
func (r *MerchantFileUploadRequest) SetFileFromPath(filePath string) error {
	file, err := os.Open(filePath)
	if err != nil {
		return fmt.Errorf("打开文件失败: %w", err)
	}
	defer file.Close()

	fileContent, err := io.ReadAll(file)
	if err != nil {
		return fmt.Errorf("读取文件内容失败: %w", err)
	}

	filename := filepath.Base(filePath)
	r.FilePath = filePath
	r.SetMeta(filename, fileContent)
	r.SetFile(fileContent)

	return nil
}

// GetFile 获取文件内容
func (r *MerchantFileUploadRequest) GetFile() io.Reader {
	return r.file
}

// GetFileName 获取文件名
func (r *MerchantFileUploadRequest) GetFileName() string {
	return r.fileName
}

// GetMeta 获取meta信息
func (r *MerchantFileUploadRequest) GetMeta() string {
	return r.Meta
}

// CheckRequiredParams 检查必需参数
func (r *MerchantFileUploadRequest) CheckRequiredParams(config *core.Config) error {
	if err := r.OrgBaseRequest.CheckRequiredParams(config); err != nil {
		return err
	}
	if r.Meta == "" {
		return fmt.Errorf("meta不能为空")
	}
	if r.file == nil {
		return fmt.Errorf("file不能为空")
	}
	return nil
}

// ImageUploadRequest 图片上传请求类
type ImageUploadRequest struct {
	MerchantFileUploadRequest
}

// GetAPIURI 获取API URI
func (r *ImageUploadRequest) GetAPIURI() string {
	return "/base/file/upload/image"
}

// VideoUploadRequest 视频上传请求类
type VideoUploadRequest struct {
	MerchantFileUploadRequest
}

// GetAPIURI 获取API URI
func (r *VideoUploadRequest) GetAPIURI() string {
	return "/base/file/upload/video"
}

// PdfUploadRequest PDF上传请求类
type PdfUploadRequest struct {
	MerchantFileUploadRequest
}

// GetAPIURI 获取API URI
func (r *PdfUploadRequest) GetAPIURI() string {
	return "/base/file/upload/pdf"
}
